package cn.clark.game.snake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.LinkedList;
import java.util.Random;

public class GamePanel extends JPanel implements ActionListener {
    // 游戏参数
    private static final int WIDTH = 600;
    private static final int HEIGHT = 600;
    private static final int UNIT_SIZE = 20;

    // 游戏状态
    private final LinkedList<Point> snake = new LinkedList<>();
    private Point food;
    private Direction direction = Direction.RIGHT;

    public boolean isRunning() {
        return isRunning;
    }

    public void setRunning(boolean running) {
        isRunning = running;
    }

    public boolean isPaused() {
        return isPaused;
    }

    public void setPaused(boolean paused) {
        isPaused = paused;
    }

    private boolean isRunning = false;
    private boolean isPaused = false;
    private Timer timer;
    private int score = 0;
    private int currentSpeed = 150;
    private final Random random = new Random();

    public GamePanel() {
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
        setBackground(Color.BLACK);
        setFocusable(true);
        addKeyListener(new MyKeyAdapter());
        initSnake();
    }

    private void initSnake() {
        snake.clear();
        snake.add(new Point(UNIT_SIZE * 2, 0));
        snake.add(new Point(UNIT_SIZE, 0));
        snake.add(new Point(0, 0));
    }

    public void startGame() {
        if (!isRunning) {
            isRunning = true;
            isPaused = false;
            score = 0;
            initSnake();
            generateFood();
            startTimer();
            requestFocusInWindow(); // 确保焦点
        }
    }

    @Override
    public void addNotify() {
        super.addNotify();
        requestFocusInWindow(); // 自动获取焦点
    }


    public void pauseGame() {
        if (isRunning) {
            isPaused = !isPaused;
            if (isPaused) timer.stop();
            else timer.start();
        }
    }

    public void resetGame() {
        stopGame();
        startGame();
    }

    public void stopGame() {
        isRunning = false;
        if (timer != null) timer.stop();
    }

    public void setGameSpeed(int speed) {
        currentSpeed = speed;
        if (timer != null) {
            timer.setDelay(currentSpeed);
            if (!isPaused) timer.restart();
        }
    }

    private void startTimer() {
        if (timer != null) timer.stop();
        timer = new Timer(currentSpeed, this);
        timer.start();
    }

    private void generateFood() {
        int x = random.nextInt(WIDTH / UNIT_SIZE) * UNIT_SIZE;
        int y = random.nextInt(HEIGHT / UNIT_SIZE) * UNIT_SIZE;
        food = new Point(x, y);
        while (snake.contains(food)) {
            x = random.nextInt(WIDTH / UNIT_SIZE) * UNIT_SIZE;
            y = random.nextInt(HEIGHT / UNIT_SIZE) * UNIT_SIZE;
            food.setLocation(x, y);
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        draw(g);
    }

    private void draw(Graphics g) {
        if (isRunning) {
            // 绘制食物
            g.setColor(Color.RED);
            g.fillOval(food.x, food.y, UNIT_SIZE, UNIT_SIZE);

            // 绘制蛇
            for (Point p : snake) {
                g.setColor(new Color(45, 180, 0));
                g.fillRect(p.x, p.y, UNIT_SIZE, UNIT_SIZE);
            }

            // 绘制信息
            g.setColor(Color.WHITE);
            g.setFont(new Font("Arial", Font.BOLD, 30));
            g.drawString("Score: " + score, 20, 40);
            g.drawString("Speed: " + currentSpeed + "ms", WIDTH - 200, 40);

            // 暂停状态
            if (isPaused) {
                g.setColor(new Color(255, 255, 255, 150));
                g.fillRect(0, 0, WIDTH, HEIGHT);
                g.setColor(Color.BLUE);
                g.setFont(new Font("Arial", Font.BOLD, 60));
                g.drawString("PAUSED", WIDTH/3, HEIGHT/2);
            }
        } else {
            // 开始前提示
            g.setColor(Color.YELLOW);
            g.setFont(new Font("Arial", Font.BOLD, 50));
            g.drawString("Press Start", WIDTH/4, HEIGHT/2);
        }
    }

    private void move() {
        Point head = snake.getFirst();
        Point newHead = new Point(head);

        switch (direction) {
            case UP: newHead.y -= UNIT_SIZE; break;
            case DOWN: newHead.y += UNIT_SIZE; break;
            case LEFT: newHead.x -= UNIT_SIZE; break;
            case RIGHT: newHead.x += UNIT_SIZE; break;
        }

        checkCollision(newHead);
        snake.addFirst(newHead);

        if (newHead.equals(food)) {
            score += 10;
            generateFood();
        } else {
            snake.removeLast();
        }
    }

    private void checkCollision(Point head) {
        // 边界检测
        if (head.x < 0 || head.x >= WIDTH || head.y < 0 || head.y >= HEIGHT) {
            gameOver();
        }
        // 自身碰撞检测
        for (int i = 1; i < snake.size(); i++) {
            if (head.equals(snake.get(i))) {
                gameOver();
                break;
            }
        }
    }

    private void gameOver() {
        isRunning = false;
        timer.stop();
        repaint();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (isRunning && !isPaused) {
            move();
            repaint();
        }
    }

    private class MyKeyAdapter extends KeyAdapter {
        @Override
        public void keyPressed(KeyEvent e) {
            int key = e.getKeyCode();

            // 空格键处理
            if (key == KeyEvent.VK_SPACE) {
                if (isRunning) {
                    pauseGame();
                } else {
                    if (timer==null||snake.isEmpty()) { // 首次启动
                        startGame();
                    } else { // 继续游戏
                        isPaused = false;
                        timer.start();
                    }
                }
                repaint();
                return;
            }

            // 仅在游戏运行时处理方向键
            if (!isRunning || isPaused) return;

            // 方向键处理
            switch (key) {
                case KeyEvent.VK_LEFT:
                    if (direction != Direction.RIGHT)
                        direction = Direction.LEFT;
                    break;
                case KeyEvent.VK_RIGHT:
                    if (direction != Direction.LEFT)
                        direction = Direction.RIGHT;
                    break;
                case KeyEvent.VK_UP:
                    if (direction != Direction.DOWN)
                        direction = Direction.UP;
                    break;
                case KeyEvent.VK_DOWN:
                    if (direction != Direction.UP)
                        direction = Direction.DOWN;
                    break;
            }
        }
    }
}